/*
 * 工具类装饰器
 */
import { registerDecorator, ValidationArguments, ValidationOptions } from 'class-validator'

export type TFlexibleDateFormat
  = | 'YYYY-MM'
    | 'YYYY-MM-DD'
    | 'YYYY-MM HH:mm'
    | 'YYYY-MM-DD HH:mm'
    | 'YYYY-MM-DD HH:mm:ss'
    | 'YYYY-MM-DD:HH-mm-ss'

const formatRegexpMap: Record<TFlexibleDateFormat, RegExp> = {
  'YYYY-MM': /^\d{4}-\d{2}$/,
  'YYYY-MM-DD': /^\d{4}-\d{2}-\d{2}$/,
  'YYYY-MM HH:mm': /^\d{4}-\d{2} \d{2}:\d{2}$/,
  'YYYY-MM-DD HH:mm': /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/,
  'YYYY-MM-DD HH:mm:ss': /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
  'YYYY-MM-DD:HH-mm-ss': /^\d{4}-\d{2}-\d{2}:\d{2}-\d{2}-\d{2}$/,
}

/**
 * 日期格式校验，支持多种 YYYY-MM 开头的日期/时间字符串
 * @example @isDateByUtils()
 * @example @isDateByUtils('YYYY-MM-DD')
 * @example @isDateByUtils(['YYYY-MM', 'YYYY-MM-DD HH:mm'])
 */
export function IsDateByUtils(
  formats?: TFlexibleDateFormat | TFlexibleDateFormat[],
  validationOptions?: ValidationOptions,
) {
  let allowedFormats = ['YYYY-MM-DD']
  if (formats) {
    allowedFormats = Array.isArray(formats) ? formats : [formats]
  }

  /**
   * object：正在被验证的类的实例，就是 DTO 的对象
   * propertyName：当前装饰器所在的字段名，就是你在 DTO 里写的属性名，比如 noticeShowTime
   */
  return function (object: object, propertyName: string) {
    registerDecorator({
      name: 'isDateByUtils',
      target: object.constructor,
      propertyName,
      options: validationOptions,
      validator: {
        validate(value: any, _args: ValidationArguments) {
          if (typeof value !== 'string')
            return false

          return allowedFormats.some(format => formatRegexpMap[format].test(value))
        },
        defaultMessage(_args: ValidationArguments) {
          return `${propertyName} must be a valid date string (${allowedFormats.join(' / ')})`
        },
      },
    })
  }
}
